package xyz.xpman.prisonerfitness.entity;

import android.annotation.SuppressLint;
import android.content.Context;
import android.database.Cursor;
import android.util.Log;

import androidx.annotation.Nullable;

import org.jetbrains.annotations.NotNull;

import java.time.LocalDate;
import java.util.Date;
import java.util.List;
import java.util.Map;

import xyz.xpman.prisonerfitness.kit.DateKit;


@SuppressWarnings("unused")
public class TrainingRecord extends BaseModel<TrainingRecord> {
    public static final String TAG = "TrainingRecord";

    public static final String ID_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String DATE_FORMAT = ID_FORMAT;
    public static final String DATE_CMP_FORMAT = "yyyy-MM-dd";

    private static final String DATE = "date";
    private static final String USED_TIME = "usedTime";

    private static final String MOVES_ID = "movesId";
    private static final String CHAPTER_ID = "chapterId";

    private static final String DIFFICULTY_ID = "difficulty";


    public static final String IS_WARM_UP_TRAINING = "isWarmUp";

    private static final String STANDARD_TIMES = "times";
    private static final String STANDARD_GROUPS = "groups";

    @SuppressLint("NewApi")
    public static final Map<String, Class<?>> attrs = Map.ofEntries(
            Map.entry(ID, Integer.class),
            Map.entry(DATE, String.class),
            Map.entry(USED_TIME, Integer.class),

            Map.entry(MOVES_ID, String.class),
            Map.entry(CHAPTER_ID, String.class),

            Map.entry(IS_WARM_UP_TRAINING, Integer.class),

            Map.entry(STANDARD_TIMES, Integer.class),
            Map.entry(STANDARD_GROUPS, Integer.class)
    );


    private static boolean init = false;

    public static final String TABLE = "training_records";



    public static void init(@Nullable Context context) {
        if (!init) {
            init = true;
            bind(new TableInfo(TABLE, attrs, TrainingRecord.class, ID));
        }
    }


    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    public @NotNull List<TrainingRecord> findByDate(@NotNull LocalDate date) {
        return findByDate(DateKit.format(date, DATE_CMP_FORMAT));
    }

    private @NotNull List<TrainingRecord> findByDate(@NotNull String date) {
        // public static final String ORDER_BY="date("+COLUMN_DATE+") desc";
        // select * from table where strftime('%Y-%m-%d', date) = '2017-05-10'
        final String sqlFmt = "select * from %s where %s";
        final String sql = String.format(sqlFmt,
                table.name, "strftime('%Y-%m-%d', date) = ?");
        Log.i(TAG, "sql: " + sql.replace("?", date));


        @SuppressLint("Recycle")
        Cursor cursor = db.rawQuery(sql, new String[]{date});

        return cursorToList(cursor);
    }




    public int countTrainingTime() {
        final String sqlFmt = "select sum(%s) as totalTime from %s";
        final String sql = String.format(sqlFmt, USED_TIME, table.name);
        @SuppressLint("Recycle")
        Cursor cursor = db.rawQuery(sql, new String[0]);

        return getCursorIntAttr(cursor, "totalTime", 0);
    }

    public int countTrainingDay() {
        // select count(*) as count
        // from (select distinct strftime(%s, %s) from %s)
        final String sqlFmt =
                "select count(*) as count " +
                "from (select distinct strftime(%s, %s) from %s)";
        final String sql = String.format(sqlFmt, "'%Y-%m-%d'", DATE, table.name);
        @SuppressLint("Recycle")
        Cursor cursor = db.rawQuery(sql, new String[0]);

        return getCursorIntAttr(cursor, "count", 0);
    }

    public int countTrainingTimes() {
        final String sqlFmt = "select count(*) as count from %s";
        final String sql = String.format(sqlFmt, table.name);
        @SuppressLint("Recycle")
        Cursor cursor = db.rawQuery(sql, new String[0]);

        return getCursorIntAttr(cursor, "count", 0);
    }



    private int getCursorIntAttr(@NotNull Cursor cursor, @NotNull String attr) {
        return getCursorIntAttr(cursor, attr, 0);
    }

    private int getCursorIntAttr_1(@NotNull Cursor cursor, @NotNull String attr) {
        return getCursorIntAttr(cursor, attr, -1);
    }

    private int getCursorIntAttr(@NotNull Cursor cursor, @NotNull String attr, int defaultValue) {
        cursor.moveToFirst();

        return processCursorDiy(cursor, (cur) -> {
            int index = cur.getColumnIndex(attr);

            if (-1 < index && index <= cur.getColumnCount()){
                return cur.getInt(index);
            }
            return defaultValue;
        });
    }

    // getter and setter
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    public String getId() {
        return getString(ID);
    }

    public void setId(String id) {
        set(ID, id);
    }


    public String getDate() {
        return getString(DATE);
    }

    @SuppressLint("NewApi")
    public void setDate(Date date) {
        set(DATE, DateKit.format(date, DATE_FORMAT));
    }

    /**
     * 获取消耗的时间，单位：秒
     * @return 消耗的时间
     */
    public int getUsedTime() {
        return getInteger(USED_TIME);
    }

    public void setUsedTime(int usedTime) {
        set(USED_TIME, usedTime);
    }

    public String getMovesId() {
        return getString(MOVES_ID);
    }

    public void setMovesId(String movesId) {
        set(MOVES_ID, movesId);
    }

    public String getChapterId() {
        return getString(CHAPTER_ID);
    }

    public void setChapterId(String chapterId) {
        set(CHAPTER_ID, chapterId);
    }



    public int getDifficulty() {
        return getInt(DIFFICULTY_ID, 0);
    }

    public void setDifficulty(int value) {
        set(DIFFICULTY_ID, value);
    }



    public boolean isWarmUp() {
        return 1 == getInt(IS_WARM_UP_TRAINING, 0);
    }

    public boolean isWarmUpTraining() {
        return isWarmUp();
    }

    public boolean getIsWarmUpTraining() {
        return isWarmUpTraining();
    }

    public void setIsWarmUpTraining(boolean isWarmUp) {
        set(IS_WARM_UP_TRAINING, isWarmUp ? 1 : 0);
    }





    public void setStandard(@NotNull TrainingStandard.Standard standard) {
        setStandardTimes(standard.getTimes());
        setStandardGroups(standard.getGroups());
    }

    public int getStandardGroups() {
        return getInteger(STANDARD_GROUPS, 0);
    }

    public void setStandardGroups(int groups) {
        set(STANDARD_GROUPS, groups);
    }

    public int getStandardTimes() {
        return getInteger(STANDARD_TIMES, 0);
    }

    public void setStandardTimes(int standardTimes) {
        set(STANDARD_TIMES, standardTimes);
    }



    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



    public static int countUsedTime(@NotNull List<TrainingRecord> records) {
        int totalUsedTime = 0;

        for (TrainingRecord record : records) {
            totalUsedTime += record.getUsedTime();
        }

        return totalUsedTime / 60;
    }

}
